////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include "ConvexHullHandler.hpp"

#include <SmegLight/Hull/ConvexHull.hpp>

#include <SmegLight/Light/LightSystem.hpp>

#include "../../tinyxml2/tinyxml2.h"
#include "../../Canvas/SmegEditorCanvas.hpp"

#include "../../Form/ConvexHullCreatorDialog.h"

////////////////////////////////////////////////////////////
/// Constructor
////////////////////////////////////////////////////////////
ConvexHullHandler::ConvexHullHandler() :
    QuadTreeOccupantHandler()
{
}

////////////////////////////////////////////////////////////
/// Copy Constructor
////////////////////////////////////////////////////////////
ConvexHullHandler::ConvexHullHandler( const ConvexHullHandler& _Copy ) :
    QuadTreeOccupantHandler( _Copy ),
    m_CurrentFilename( _Copy.m_CurrentFilename )
{
}

////////////////////////////////////////////////////////////
/// Init the handler and setup the properties
/// QuadTreeOccupantHandler::InitFromGrid need to be called AFTER the specialized class
////////////////////////////////////////////////////////////
bool ConvexHullHandler::InitFromGrid( wxPropertyGrid* _pPropertyGrid ) {
    bool creationSucess = false;

    m_CurrentFilename = wxEmptyString;

    // Angle will be set in BaseObjectHandler::Init, that is why we need to call it at the END
    m_pObject = new smeg::light::ConvexHull();

    smeg::light::ConvexHull* convexHull = static_cast< smeg::light::ConvexHull* >( m_pObject );

    if ( QuadTreeOccupantHandler::InitFromGrid( _pPropertyGrid ) ) {
        // Load from a file or Create a New ConvexHull
        wxMessageDialog* dlg = new wxMessageDialog( m_pCanvas->GetParent(), 
                                            _T("Do you want to Load from an existing file or Create a new ConvexHull ?"),
                                            _T("ConvexHull Creator"),
                                            wxYES_NO | wxCANCEL | wxICON_QUESTION );
        dlg->SetYesNoLabels("Load", "Create");

        int ret = dlg->ShowModal();
        dlg->Destroy();

        if ( wxID_YES == ret ) {
            wxFileDialog* fileDlg = new wxFileDialog( m_pCanvas->GetParent(),
                                            _T("Load an existing ConvexHull..."),
                                            wxEmptyString,
                                            wxEmptyString,
                                            "CVX Files (*.cvx)|*.cvx",
                                            wxFD_OPEN | wxFD_FILE_MUST_EXIST );
            if ( wxID_CANCEL != fileDlg->ShowModal() && convexHull->LoadShape( fileDlg->GetPath() )) {
                m_CurrentFilename = fileDlg->GetPath(); 
                creationSucess = true;
            }
            fileDlg->Destroy();
        } else if ( wxID_NO == ret ) {
            ConvexHullCreatorDialog* dlg = new ConvexHullCreatorDialog( m_pCanvas->GetParent(), convexHull );
            dlg->ShowModal();

            if ( convexHull->GetNumVertices() > 0 ) {
                creationSucess = true;
                m_CurrentFilename = dlg->GetFilename();
            }
            dlg->Destroy();
        }
    }

    if ( !creationSucess ) {
        smeg::light::LightSystem::GetInstance()->RemoveHull( convexHull );
        m_pObject = NULL;
    }

    return creationSucess;
}
    
////////////////////////////////////////////////////////////
/// Init the handler from an XMLElement
/// QuadTreeOccupantHandler::InitFromXML need to be called AFTER the specialized class
////////////////////////////////////////////////////////////
bool ConvexHullHandler::InitFromXML( tinyxml2::XMLElement* _pElement, const wxString& _ProjectPath ) {
    // Get the infos
    tinyxml2::XMLElement* paramElem = _pElement->FirstChildElement( "Param" );

    m_pObject = new smeg::light::ConvexHull( m_pCanvas->GetViewCenter() );
    smeg::light::ConvexHull* convexObj = static_cast< smeg::light::ConvexHull* >( m_pObject );
    
    if ( QuadTreeOccupantHandler::InitFromXML( _pElement, _ProjectPath ) ) {
        while ( paramElem ) {
            wxString paramName = paramElem->Attribute( "name" );

            if ( "File" == paramName ) {
                m_CurrentFilename = wxFileName( _ProjectPath + wxFileName::GetPathSeparator() + paramElem->Attribute( "value" ) );
                m_CurrentFilename.Normalize();

                if ( !convexObj->LoadShape( m_CurrentFilename.GetFullPath() ) ) {
                    smeg::light::LightSystem::GetInstance()->RemoveHull( convexObj );
                    m_pObject = NULL;
                    m_CurrentFilename = wxEmptyString; 
                    return false;
                }
            }

            paramElem = paramElem->NextSiblingElement( "Param" );
        }
    } else {
        smeg::light::LightSystem::GetInstance()->RemoveHull( convexObj );
        m_pObject = NULL;
        return false;
    }

    return true;
}
    
////////////////////////////////////////////////////////////
/// Add the created object to the scene
////////////////////////////////////////////////////////////
void ConvexHullHandler::AddObjectToScene() {
    smeg::light::LightSystem::GetInstance()->AddHull( static_cast< smeg::light::ConvexHull* >( m_pObject ) );
}
    
////////////////////////////////////////////////////////////
/// Remove the created object from the scene
////////////////////////////////////////////////////////////
void ConvexHullHandler::RemoveObjectFromScene( bool _bDeleteObject ) {
    smeg::light::LightSystem::GetInstance()->RemoveHull( static_cast< smeg::light::ConvexHull* >( m_pObject ), _bDeleteObject );
    if ( _bDeleteObject ) {
        m_pObject = NULL;
    }
}
    
////////////////////////////////////////////////////////////
/// Handle the change of a property and apply it to the object
////////////////////////////////////////////////////////////
bool ConvexHullHandler::OnPropertyChanged( wxPropertyGrid* _pPropertyGrid, wxPGProperty* _pChangedProperty ) {
    if ( QuadTreeOccupantHandler::OnPropertyChanged( _pPropertyGrid, _pChangedProperty ) ) {
        return true;
    }

    smeg::light::ConvexHull * convexObj = static_cast< smeg::light::ConvexHull* >( m_pObject );
    
    // Handle changes in values, as needed
    const wxString& propName(_pChangedProperty->GetName());
    if ( "File" == propName ) {
        wxString fileName = _pChangedProperty->GetValue().GetString();
        if ( convexObj->LoadShape( fileName ) ) {
            m_CurrentFilename = fileName; 
        } else {
	        wxMessageBox(_T("Fail To load shape!\n"),
	                        _T("ConvexHull loading Error"),
	                        wxOK | wxICON_ERROR,
                            m_pCanvas->GetParent());
            _pChangedProperty->SetValueFromString( wxEmptyString );
            m_CurrentFilename = wxEmptyString; 
        }
    } else {
        return false;
    }

    return true;
}

////////////////////////////////////////////////////////////
/// Handle the double click on a property
////////////////////////////////////////////////////////////
bool ConvexHullHandler::OnPropertyDoubleClick( wxPropertyGrid* _pPropertyGrid, wxPGProperty* _pChangedProperty ) {
    const wxString& propName(_pChangedProperty->GetName());
    if ( "File" == propName ) {
        ConvexHullCreatorDialog dlg = ConvexHullCreatorDialog( m_pCanvas->GetParent(), static_cast< smeg::light::ConvexHull* >( m_pObject ) );
        dlg.ShowModal();

        if ( wxEmptyString != dlg.GetFilename().GetFullPath() && m_CurrentFilename != dlg.GetFilename() ) {
            m_CurrentFilename = dlg.GetFilename();
        }
        dlg.Destroy();

        return true;
    } else {
        return QuadTreeOccupantHandler::OnPropertyDoubleClick( _pPropertyGrid, _pChangedProperty );
    }
}
   
////////////////////////////////////////////////////////////
/// Create an XML string with the value of the object
////////////////////////////////////////////////////////////
wxString ConvexHullHandler::InnerXMLString( const wxString& _ProjectPath, const wxString& _Tab ) const {
    smeg::light::ConvexHull * convexObj = static_cast< smeg::light::ConvexHull* >( m_pObject );
    wxFileName tmpRelative( m_CurrentFilename );
    tmpRelative.MakeRelativeTo( _ProjectPath );

    return QuadTreeOccupantHandler::InnerXMLString( _ProjectPath, _Tab ) +
        _Tab + wxT( "<Param name=\"File\" value=\"" ) + tmpRelative.GetFullPath() + wxT( "\" />\n" );
}